/* =========================================================================
 *
 *   The traffic processor.
 *
 *   Development by Sedelnikov Alexander (Bigking).
 *
 * =========================================================================
 */

#ifndef __TRAFFIC_PARSER_H__
#define __TRAFFIC_PARSER_H__


#include "common.h"


//-----------------------------------------------------------------------//
class cfile_base
{


protected:
    void                *ptr;


public:
    cfile_base()          { ptr = NULL; }
    virtual ~cfile_base() {             }


    virtual void  open( const char *name ) {    }
    virtual void  close() {    }
    virtual int   eof() {    }
    virtual int   gets( char *text, int max_len ) {    }


//-----------------------------------------------------------------------//
EXCEPTION( e_open );


};


//-----------------------------------------------------------------------//
class cfile : public cfile_base
{


public:
    cfile() : cfile_base()   {    }
    virtual ~cfile();

    void   open( const char *name );
    void   close();
    int    eof();
    int    gets( char *text, int max_len );


};


//-----------------------------------------------------------------------//
class cgzfile : public cfile_base
{


public:
    cgzfile() : cfile_base() {    }
    virtual ~cgzfile();

    void  open( const char *name );
    void  close();
    int   eof();
    int   gets( char *text, int max_len );


};


//-----------------------------------------------------------------------//
struct parser_item
{


    ulong       ip_src;
    ulong       ip_dst;

    ushort      port_src;
    ushort      port_dst;

    ulong       packets;
    ulong       bytes;   // @fixme This may be a problem when traffic is incrased

    ushort      protocol;


};


//-----------------------------------------------------------------------//
struct trf_gth
{


    ulong               ip;

    ulong               tc_id;

    unsigned long long  volume_in;
    unsigned long long  volume_out;

    //-----------------------------------------------------------------------//
    bool operator == ( const trf_gth &v ) const
    {
        return v.ip    == ip    &&
               v.tc_id == tc_id;
    }

    //-----------------------------------------------------------------------//
    ulong operator ! () const
    {
        return ip ^ ( ( ip >> 8 ) ^ tc_id );
    }

    //-----------------------------------------------------------------------//
    void operator += ( const trf_gth &v )
    {
        volume_in  += v.volume_in;
        volume_out += v.volume_out;
    }


};


//-----------------------------------------------------------------------//
struct time_stamp
{

    //-----------------------------------------------------------------------//
    long        year, month, day,
                hour, minute, second;


    const static long   months[];
    const static long   since_year;


    //-----------------------------------------------------------------------//
    long to_second() const
    {
        long  days = 0,
              y    = year - since_year;

        const long dpqy = 365 * 3 + 366,
                   dpy  = 365;


        days  = y / 4;
        y    -= days * 4;

        days *= dpqy;


        if( y != 0 )
            days += 366 + ( y - 1 ) * dpy;

        days += months[ month - 1 ];

        if( y == 0 && month >= 3 )
            days += 1;

        days += day - 1;


        return ( ( days * 24 + hour ) * 60 + minute ) * 60 + second;
    }

    //-----------------------------------------------------------------------//
    long to_minute() const
    {
        return to_second() / 60;
    }

    //-----------------------------------------------------------------------//
    long to_hour() const
    {
        return to_second() / 3600;
    }

    //-----------------------------------------------------------------------//
    long to_day() const
    {
        return to_second() / 86400;
    }

    //-----------------------------------------------------------------------//
    void from_second( const long seconds )
    {
        const long seconds_per_day = 24 * 60 * 60;
        const long dpqy = 365 * 3 + 366,
                   dpy  = 365;

        long tmp_sec = seconds;

        year       = ( tmp_sec / ( dpqy * seconds_per_day ) );
        tmp_sec   -= year * ( dpqy * seconds_per_day );

        year  = year * 4 +
                since_year;

        if( tmp_sec - 366 * seconds_per_day >= 0 )
        {
            year       += 1;
            tmp_sec   -= 366 * seconds_per_day;

            year       += tmp_sec / ( 365 * seconds_per_day );
            tmp_sec   -= ( tmp_sec / ( 365 * seconds_per_day ) ) * 365 * seconds_per_day;
        }

        long m = 0;

        for( month = 1; month < 12; month++ )
        {
            m = months[ month ];

            if( month >= 2 && ( year % 4 ) == 0 )
                m++;

            if( tmp_sec - m * seconds_per_day < 0 )
            {
                m = months[ month - 1 ];
                if( month > 2 && ( year % 4 ) == 0 )
                    m++;
                break;
            }
        }

        tmp_sec   -= m * seconds_per_day;

        day        = tmp_sec / seconds_per_day + 1;

        tmp_sec   -= ( day - 1 ) * seconds_per_day;


        hour       = tmp_sec / 3600;
        tmp_sec   -= hour * 3600;

        minute = tmp_sec / 60;
        second = tmp_sec - minute * 60;
    }

    //-----------------------------------------------------------------------//
    void from_minute( const long minute )
    {
        from_second( minute * 60 );
    }

    //-----------------------------------------------------------------------//
    void from_hour( const long minute )
    {
        from_second( minute * 3600 );
    }

    //-----------------------------------------------------------------------//
    void from_day( const long minute )
    {
        from_second( minute * 86400 );
    }


};


//-----------------------------------------------------------------------//
struct source_file
{
    char          file_name[ FILENAME_MAX ];
    time_stamp    stamp;
    time_stamp    stamp_trunc;
    ulong         interval; // since 2000
    ulong         interval_trunc; // since 2000

    //-----------------------------------------------------------------------//
    static bool sort_cmp_func( const source_file &s1,
                               const source_file &s2 )
    {
        return s1.interval < s2.interval;
    }

};


//-----------------------------------------------------------------------//
class cparser
{


protected:
    cfile_base      *input;


public:
    cparser( )                        {               }
    cparser( cfile_base *f )          { input = NULL; }
    virtual ~cparser()                {               }

    virtual time_stamp get_time( const char *name ) = 0;

    virtual void  start( const char *name ) {    }
    virtual void  end()
    {
        if( input != NULL )
            input->close();
    }
    virtual int   get_next( parser_item &item ) {    }

    void  set_input( cfile_base *f )
    {
        input = f;
    }


//-----------------------------------------------------------------------//
EXCEPTION( e_wrong  );
EXCEPTION( e_demage );


};


#endif
